package com.bkgy.util;

import com.baosight.hdjni.HDErrcode;
import com.baosight.hdsdk.HDConnectionFactory;
import com.baosight.hdsdk.HDDataProvider;
import com.baosight.hdsdk.HDServerFactory;
import com.baosight.hdsdk.HDTagManager;
import com.baosight.hdsdk.domain.data.HDDataConnection;
import com.baosight.hdsdk.domain.data.HDDataServer;
import com.baosight.hdsdk.domain.data.HDRecord;
import com.baosight.hdsdk.exception.HDSdkException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@Service
@Slf4j
public class SDKUtils {

    @Value("${sdk_ip}")
    private String sdkIP;

    @Value("${reduceTime}")
    private Long reduceTime;

    @Value("${sdk_port}")
    private Integer sdkPort;

    @Value("${sdk_username}")
    private String sdkUserName;

    @Value("${sdk_password}")
    private String sdkPassword;

    HDDataConnection dataConns = null;

    /**
     * 获取宝信SDK连接
     *
     * @return
     */
    public HDDataConnection getConnect() {
        HDDataConnection dataConn = null;
        try {
            HDDataServer server = HDServerFactory.getHDDataServer(this.sdkIP, this.sdkPort, "", this.sdkPort);
            dataConn = HDConnectionFactory.getHDDataConnection(server);
            dataConn.loginToServer("admin", "admin");
            return dataConn;
        } catch (HDSdkException var3) {
            log.error("宝信sdk服务器登录失败,ErrorCode:"+var3.getErrorCode());
            //var3.printStackTrace();
            //var3.getErrorCode();
            return dataConn;
        }
    }

    public HDDataConnection getConnects() {
        try {
            if (dataConns == null || ObjectUtils.isEmpty(dataConns)) {
                HDDataServer server = HDServerFactory.getHDDataServer(sdkIP, sdkPort, "", sdkPort);
                dataConns = HDConnectionFactory.getHDDataConnection(server);
                dataConns.loginToServer(sdkUserName, sdkPassword);
            }
            return dataConns;
        } catch (HDSdkException e) {
            log.error("通过SDK登录宝信IHDB服务器失败,ErrorCode:"+e.getErrorCode());
            //System.out.println("通过SDK登录宝信IHDB服务器失败!失败原因是：" + e.getMessage());
            e.printStackTrace();
        }
        return dataConns;
    }

    /**
     * 根据变量名查找tagId
     *
     * @param tagName    变量名
     * @param tagManager connect
     * @return
     */
    public Integer findTagId(String tagName, HDTagManager tagManager) {
        Integer id = null;
        try {
            id = tagManager.getTagIDByTagName(tagName);
            return id;
        } catch (HDSdkException e) {
            log.error("获取宝信报警id失败,ErrorCode:"+e.getErrorCode());
            //e.printStackTrace();
        }
        return id;
    }


    /**
     * 根据变量名查找tagId
     *
     * @param tagNameList 变量名集合
     * @param tagManager  connect
     * @return
     */
    public List<ImmutablePair<Integer, Integer>> findTagIDsByTagNames(List<String> tagNameList, HDTagManager tagManager) {
        List<ImmutablePair<Integer, Integer>> tagIDsByTagNames = null;
        try {
            tagIDsByTagNames = tagManager.getTagIDsByTagNames(tagNameList, new HDErrcode());
            return tagIDsByTagNames;
        } catch (HDSdkException e) {
            log.error("获取宝信报警id失败,ErrorCode:"+e.getErrorCode());
            e.printStackTrace();
        }
        return tagIDsByTagNames;
    }

    public String findDataOneById(Integer id, HDDataProvider provider) {
        String result = null;
        try {
            HDRecord hdRecord = provider.querySnapshotByTagID(id);
            result = hdRecord.getValueStr();
            return result;
        } catch (HDSdkException e) {
            log.error("获取宝信单值出错,ErrorCode:"+e.getErrorCode());
            e.printStackTrace();
        }
        return result;
    }

    public String findDataOneById2(String tagName,Integer id, HDDataProvider provider) {
        String result = null;
        try {
            HDRecord hdRecord = provider.querySnapshotByTagID(id);
            result = hdRecord.getValueStr();
            return result;
        } catch (HDSdkException e) {
            log.error("tagName:"+tagName+"获取宝信单值出错,ErrorCode:"+e.getErrorCode());
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 查询一段时间内 对应tagID的值
     *
     * @param id
     * @param provider
     * @param timeFrom
     * @param timeTo
     * @return
     */
    public List<HDRecord> findMsgByIdAndTime(Integer id, HDDataProvider provider, LocalDateTime timeFrom, LocalDateTime timeTo) {
        Date dateFrom = Date.from(timeFrom.toInstant(ZoneOffset.of("+8")));
        Date dateTo = Date.from(timeTo.toInstant(ZoneOffset.of("+8")));
        if (ObjectUtils.isEmpty(provider)) {
            log.error("宝信连接为空");
            return null;
        }
        List<HDRecord> list = null;
        try {
            list = provider.queryTagHisRawRecords(id, dateFrom, dateTo);
        } catch (Exception e) {
            log.error("获取宝信实体出错");
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 以不同插值算法，查询Tag点的历史插值记录，查询结果按时间正序返回
     *
     * @param tagId
     * @param provider
     * @param timeFrom
     * @param timeTo
     * @param intervalInMs
     * @param errCode
     * @return
     */
    public List<Double> findQueryTagHisInterRecords(int tagId, HDDataProvider provider, LocalDateTime timeFrom, LocalDateTime timeTo, long intervalInMs, HDErrcode errCode) {
        Date dateFrom = Date.from(timeFrom.toInstant(ZoneOffset.of("+8")));
        Date dateTo = Date.from(timeTo.toInstant(ZoneOffset.of("+8")));
        if (ObjectUtils.isEmpty(provider)) {
            log.error("宝信连接为空");
            return null;
        }
        List<ImmutablePair<HDRecord, Integer>> list = null;
        List<Double> hdRecordList = new ArrayList<>();
        try {
            list = provider.queryTagHisInterRecords(tagId, dateFrom, dateTo, intervalInMs, errCode);
            for (ImmutablePair<HDRecord, Integer> hdRecordIntegerImmutablePair : list) {
                HDRecord left = hdRecordIntegerImmutablePair.getLeft();
                if (StringUtils.hasText(left.getValueStr())) {
                    hdRecordList.add(Double.parseDouble(left.getValueStr()));
                } else {
                    hdRecordList.add(null);
                }
            }
        } catch (HDSdkException e) {
            log.error("获取宝信实体出错,ErrorCode:"+e.getErrorCode());
            e.printStackTrace();
        }
        return hdRecordList;

    }

    /**
     * @param id
     * @param provider
     * @param time
     * @return
     */
    public List<String> findDataOneByTime(Integer id, HDDataProvider provider, String time) {
        LocalDateTime now = LocalDateTime.now().minusMinutes(reduceTime);
        LocalDateTime before = now.minusSeconds(Long.valueOf(time));
        Date local = Date.from(now.atZone(ZoneId.systemDefault()).toInstant());
        Date from = Date.from(before.atZone(ZoneId.systemDefault()).toInstant());

        List<String> result = new ArrayList<>();
        try {
            List<HDRecord> hdRecords = provider.queryTagHisRawRecords(id, from, local);
            hdRecords.forEach(t -> result.add(t.getValueStr()));
            return result;
        } catch (HDSdkException e) {
            log.error("获取宝信时间段出错,ErrorCode:"+e.getErrorCode());
            e.printStackTrace();
        }
        return result;
    }
}
